[Prism] Schedule consumers of a self checkpointing source - #39572
Open
Eliaaazzz wants to merge 1 commit into
Open
[Prism] Schedule consumers of a self checkpointing source#39572Eliaaazzz wants to merge 1 commit into
Eliaaazzz wants to merge 1 commit into
Conversation
Contributor
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
Contributor
|
Checks are failing. Will not request review until checks are succeeding. If you'd like to override that behavior, comment |
Fixes apache#39446. An unbounded source SDF that returns a process continuation residual has that residual re-queued as a pending element carrying the input element's event time, MinTimestamp for an Impulse rooted source, so the stage's watermark never advances. updateWatermarks returns no refreshes when the output watermark does not move, and PersistBundle marked only the producing stage as changed, so a consumer that was just handed pending elements was never surfaced to the scheduler. Its elements accumulated forever. checkForQuiescence cannot catch this, because the source stays schedulable, so the job live locks instead of failing fast. PersistBundle now records the consumers that accepted data, and updateWatermarks hands them to the scheduler on the path where the output watermark does not advance. Recording is gated on any bundle having returned a residual, so a pipeline that never self checkpoints keeps its previous bundle scheduling. bundleReady additionally lets a stateful stage with no side inputs run on pending data alone, under the same gate, since statefulStageKind.buildEventTimeBundle takes data at any watermark and gates only timers. Its stillSchedulable now requires buildable work, and a key that supplies nothing no longer consumes the OneKeyPerBundle slot, is not marked in progress, and does not hold the bundle's minimum timestamp. A consumer that reads a side input still waits on the watermark, since side input readiness is derived from it.
Eliaaazzz
force-pushed
the
fix-39446-prism-continuation-watermark
branch
from
August 1, 2026 00:09
d147583 to
feddf87
Compare
Contributor
|
Assigning reviewers: R: @jrmccluskey for label go. Note: If you would like to opt out of this review, comment Available commands:
The PR bot will only process comments in the main thread (not review comments). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #39446.
The bug
An unbounded source SDF that returns
ProcessContinuation.resume()has its residual re-queued byreElementResidualsas a pending element carrying the input element's event time, which for an Impulse rooted source ismtime.MinTimestamp. That pinsminPendingTimestampLocked, so the stage's watermark never advances.updateWatermarksreturns no refreshes when the output watermark does not move, andPersistBundlemarked only the producing stage as changed. So a consumer that had just been handed pending elements was never inserted intoem.changedStages,bundleReadywas never called for it, and its elements accumulated forever.This is worse than the issue describes: it starves plain ordinary consumers too, not only stateful ones, and it survives transitively through a chain of stages.
checkForQuiescencecannot catch it, because the source stage stays schedulable, so the job live locks rather than failing fast.Reproduced at the element manager level before fixing. Pre-fix, across 5 source bundles:
The fix
PersistBundlerecords the consumers that accepted data intostageState.consumersWithNewData, andupdateWatermarkshands that set to the scheduler on thenewOut <= ss.outputpath, clearing it on the advancing path where the normal return already lists every consumer. Routing the wake-up throughupdateWatermarksis what keeps a pipeline whose watermark advances on exactly its previous schedule.em.sawResidual, latched the first time any bundle returns a residual. A pipeline that never self checkpoints never populates the set, so its bundle scheduling is unchanged. This matters: an earlier revision that recorded unconditionally changed bundle packing and brokeTestRunner_Pipelines/flatten_to_sideInputat-count=20.bundleReadylets a stateful stage with no side inputs run on pending data alone, sincestatefulStageKind.buildEventTimeBundlealready takes data at any watermark and gates only timers. ItsstillSchedulablenow requires buildable work so a key holding only a future timer cannot spin against the relaxed gate, and such a key no longer consumes theOneKeyPerBundleslot, is not marked in progress, and does not hold the bundle's minimum timestamp.What is deliberately unchanged
BundleApplication.output_watermarkssays an unreported estimate meansMIN_TIMESTAMP, and Java'sProcessFnholds atfutureOutputWatermark ?? elementTimestamp. A pinnedMIN_TIMESTAMPoutput watermark for a source that reports no estimate is the spec, so the TODO the issue points at is not where the defect is.GetSideDatafilters non global windows by the bundle watermark, so relaxing this would let a bundle read a partial or empty side input. That is worse than waiting. Fixing it properly means changing how side inputs are materialized for every stage, which I would rather do separately with your input.Testing
New
elementmanager_continuation_test.go, all teeth checked by reverting each half of the fix independently:TestPersistBundle_ContinuationResidualConsumers, ordinary and stateful consumers of a source that self checkpoints forever.TestPersistBundle_ContinuationResidualTransitive,srcself checkpoints,midreturns no residual of its own,sinktwo stages down.TestPersistBundle_ContinuationResidualWatermark, pins theoutput_watermarkscontract in both directions.TestStatefulBuildEventTimeBundle_OneKeyPerBundle, a key headed by a future timer must not consume the single key slot, and must not enternewKeysor holdminTs.Green:
go test ./pkg/beam/runners/prism/... -count=1,-run "TestRunner_Pipelines/flatten" -count=20, and the new tests at-count=50.Thank you for your contribution! Follow this checklist to help us incorporate your contribution quickly and easily:
R: @username).addresses #123), if applicable. This will automatically add a link to the pull request in the issue. If you would like the issue to automatically close on merging the pull request, commentfixes #<ISSUE NUMBER>instead.CHANGES.mdwith noteworthy changes.See the Contributor Guide for more tips on how to make review process smoother.
To check the build health, please visit https://github.com/apache/beam/blob/master/.test-infra/BUILD_STATUS.md